package bizzard.client;
import bizzard.shared.*;
import java.util.*;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.*;
import com.google.gwt.user.client.ui.FormPanel.SubmitCompleteEvent;
import com.google.gwt.user.client.ui.FormPanel.SubmitCompleteHandler;


//+----------------------------------------------------------------------+
//| ViewTroll
//|
//| widget                      :       panel principal
//| troll                       :       troll en cours de modification
//| nom_troll           :   input pour le nom du troll
//| list_compLabel      :       liste de Label des competences du troll
//| list_compInput      :   liste d'input pour les points associés à chaque competence
//| button_p*           :   bouton "+" pour ajouter un point à la competence
//| button_m*           :   bouton "-" pour enlever un point à la competence
//| button_save         :   bouton "enregistrer" pour créer ou modifier un troll
//| button_empty        :       bouton "vider les champs"
//| button_del          :   bouton "supprimer" pour supprimer un troll
//|
//| - affiche la liste de troll sous forme texte
//+----------------------------------------------------------------------+
public class ViewTroll extends Composite{

        private static ViewTroll SINGLETON;
        private VerticalPanel widget = new VerticalPanel();
        private HorizontalPanel dualPanel = new HorizontalPanel();
        private VerticalPanel imagePanel = new VerticalPanel();
        private VerticalPanel formPanel = new VerticalPanel();
       
    private HashMap<String, Race> races = new HashMap<String, Race>();
        private Troll troll;
       
        public TextBox nom_troll = new TextBox();
        @SuppressWarnings("serial") private ArrayList<Label> list_compLabel = new ArrayList<Label>() {{ add(new Label("attaque")); add(new Label("degats")); add(new Label("esquive")); add(new Label("regeneration")); add(new Label("points de vie")); add(new Label("caract1")); add(new Label("caract2")); }};
        @SuppressWarnings("serial") private ArrayList<TextBox> list_compInput = new ArrayList<TextBox>() {{ add(new TextBox()); add(new TextBox()); add(new TextBox()); add(new TextBox()); add(new TextBox()); add(new TextBox()); add(new TextBox());}};
        private Button button_p1, button_m1, button_p2, button_m2, button_p3, button_m3, button_p4, button_m4, button_p5, button_m5, button_p8, button_m8, button_p9, button_m9;
        private Button button_save, button_empty, button_del;
       
        private ListBox dropBox = new ListBox();
        private HorizontalPanel panel_carac1 = new HorizontalPanel();
        private HorizontalPanel panel_carac2 = new HorizontalPanel();
       
        private Button uploadSubmitButton = new Button("Envoyer sur le serveur");
        private VerticalPanel panel = new VerticalPanel();
        private FormPanel uploadForm = new FormPanel();
        private FileUpload upload = new FileUpload();
        private HTML messageServeur = new HTML();
        String erreur = null;
       
        private String img_default = "http://placehold.it/100x100"; //image du troll par defaut
    	private String directory = "./trolls/img";
        private String img = img_default;
       
        public ViewTroll() {
                SINGLETON = this;
       
        initWidget(widget);
        widget.addStyleName("view viewtroll");
        widget.setHorizontalAlignment(VerticalPanel.ALIGN_LEFT);
       
        //*********************************************************//
        //              Nom du troll
        //********************************************************//
                HorizontalPanel panel_nom = new HorizontalPanel();
                panel_nom.addStyleName("row");
                Label nom = new Label("Nom");
                panel_nom.add(nom);
                panel_nom.add(getNom_troll());
        //*********************************************************//
        //              Caracteristiques
        //********************************************************//
                HorizontalPanel panel_comp1 = new HorizontalPanel();
                panel_comp1.addStyleName("row");
                button_p1 = new Button("+");
                button_m1 = new Button("-");
                addCaracteristique(list_compLabel.get(0), list_compInput.get(0), button_p1, button_m1, panel_comp1, "normal");

                HorizontalPanel panel_comp2 = new HorizontalPanel();
                panel_comp2.addStyleName("row");
                button_p2 = new Button("+");
                button_m2 = new Button("-");
                addCaracteristique(list_compLabel.get(1), list_compInput.get(1), button_p2, button_m2, panel_comp2, "normal");

                HorizontalPanel panel_comp3 = new HorizontalPanel();
                panel_comp3.addStyleName("row");
                button_p3 = new Button("+");
                button_m3 = new Button("-");
                addCaracteristique(list_compLabel.get(2), list_compInput.get(2), button_p3, button_m3, panel_comp3, "normal");

                HorizontalPanel panel_comp4 = new HorizontalPanel();
                panel_comp4.addStyleName("row");
                button_p4 = new Button("+");
                button_m4 = new Button("-");
                addCaracteristique(list_compLabel.get(3), list_compInput.get(3), button_p4, button_m4, panel_comp4, "normal");
             
                HorizontalPanel panel_comp5 = new HorizontalPanel();
                panel_comp5.addStyleName("row");
                button_p5 = new Button("+");
                button_m5 = new Button("-");
                addCaracteristique(list_compLabel.get(4), list_compInput.get(4), button_p5, button_m5, panel_comp5, "normal");
       
        //*********************************************************//
        //              Race
        //********************************************************//
               
                HorizontalPanel panel_race = new HorizontalPanel();
                panel_race.addStyleName("row");
                Label nom_caract7 = new Label("Race");

                dropBox.addChangeHandler(new ChangeHandler() {
                    public void onChange(ChangeEvent event) {
                      showRace(dropBox.getItemText(dropBox.getSelectedIndex()));
                    }
                  });
                panel_race.add(nom_caract7);
                panel_race.add(dropBox);
               
                panel_carac1.addStyleName("row");
                panel_carac2.addStyleName("row");
       
        //*********************************************************//
        //              Boutons enregistrer/supprimer
        //********************************************************//
                HorizontalPanel panel_action = new HorizontalPanel();
                panel_action.addStyleName("row");
               
                button_del = new Button("Supprimer");
                button_del.setStyleName("action_btn hidden");
                button_del.addClickHandler(new ClickHandler() {
                    public void onClick(ClickEvent event) {
                    	//TODO demander confirmation avant de supprimer le troll
                    	if(troll!=null) {
                    		Bizzard.get().deleteTroll(troll, "delete");
                    		Bizzard.get().updateTrolls();
                    		clearView();
                    	}
                    }
                });
                panel_action.add(button_del);
               
                button_save = new Button("Enregistrer");
                button_save.setStyleName("action_btn");
                button_save.getElement().setId("save");
                button_save.setEnabled(true);
                button_save.addClickHandler(new ClickHandler() {
                    @Override
                    public void onClick(ClickEvent event) {
                       
                        erreur = "Veuillez :\n";
                        if (getNom_troll().getValue() == ""){ erreur = erreur + "- Renseigner le nom de votre troll\n";}
                        if (max_caract() != false) { erreur = erreur + "- Attribuer tous les points de caractéristiques\n";}
                        if (dropBox.getSelectedIndex() == 0) { erreur = erreur + "- Selectionner une race\n";}
                        else if (max_caract_spe() != false) { erreur = erreur + "- Attribuer tous les points de compétences";}

                        if (erreur.contentEquals("Veuillez :\n")){

                        	String msg = "";
                        	
                        	//on crée un troll
                        	if(troll==null) { 
                        		troll = new Troll();
                        		msg = "Le troll a bien été crée";
                        	}
                        	//on modifie un troll => on le supprime pour le recreer
                        	else { 
                        		//si on renomme le troll et qu'on upload une nouvelle image on supprime l'ancienne image
                        		if(!troll.getName().contentEquals(getNom_troll().getValue()) && !troll.getImg().contentEquals(img)) Bizzard.get().deleteTroll(troll, "rename");
                        		else Bizzard.get().deleteTroll(troll, ""); 
                        			
                        		msg = "Le troll a bien été modifié";	
                        	}

                            troll.clear();
                            
                            for (int i = 0 ; i < 5; i++){
                                    troll.addCompetence(new Attribut(list_compLabel.get(i).getText()),Integer.parseInt(list_compInput.get(i).getValue()));
                            }
                            for (int i = 5 ; i < 7; i++){
                                    troll.addCaractere(new Attribut(list_compLabel.get(i).getText()),Integer.parseInt(list_compInput.get(i).getValue()));
                            }

                            troll.setName(getNom_troll().getValue());
                            
                            //si on a envoyé une image on la renomme avec le nom du troll
                            if(!img.contentEquals(img_default)) {
                            	Bizzard.get().renameImg(img, troll.getName());
                            	troll.setImg(directory + "/" + getValeur_nom_troll() + img.substring(img.lastIndexOf(".")));
                            }
                            //sinon c'est l'image par defaut
                            else
                            	troll.setImg(img);
                            	
                            troll.setRace(new Race (dropBox.getValue(dropBox.getSelectedIndex())));
                            Bizzard.get().saveTroll(troll);
                            
                            Window.alert(msg);
                            setTroll(troll);
                            
                        }else{
                            Window.alert(erreur);
                        }
                    }
                });
                panel_action.add(button_save);
               
                button_empty = new Button("Vider les champs");
                button_empty.setStyleName("action_btn");
                button_empty.getElement().setId("empty");
                button_empty.setEnabled(true);
                button_empty.addClickHandler(new ClickHandler() {
                    @Override
                    public void onClick(ClickEvent event) {
                        vider_champs();
                    }
                });
                panel_action.add(button_empty);
               
                widget.setStyleName("viewtroll");
                widget.add(dualPanel);
                dualPanel.setStyleName("panel");
                       
	            //a gauche
	            upload_image(uploadSubmitButton);
	            dualPanel.add(imagePanel);
	           
	            //a droite
	            formPanel.add(panel_nom);
	            formPanel.add(panel_comp1);
	            formPanel.add(panel_comp2);
	            formPanel.add(panel_comp3);
	            formPanel.add(panel_comp4);
	            formPanel.add(panel_comp5);
	            formPanel.add(panel_race);
	            formPanel.add(panel_carac1);
	            formPanel.add(panel_carac2);
	            formPanel.add(panel_action);
	            dualPanel.add(formPanel);
               
        }
        //****************************************************************//
        // Afficher les competences specifiques selon le choix de la race
        //****************************************************************//
        private void showRace(String race) {
                panel_carac1.clear(); panel_carac2.clear();
                ArrayList<Attribut> att = new ArrayList<Attribut>();
               
                if(troll!=null && troll.getRace().getName().contentEquals(race)) {
                        HashMap<Attribut, Integer> hashmap = troll.getCaracteres();
                        for (Attribut item : hashmap.keySet()) {
                                att.add(item);
                }                      
                list_compInput.get(5).setText(hashmap.get(att.get(0)) + "");
                list_compInput.get(6).setText(hashmap.get(att.get(1)) + "");
                }
                else {
                att = races.get(race).getCaracteristiques();
                list_compInput.get(5).setText("0");
                list_compInput.get(6).setText("0");
                }
               
                button_p8 = new Button("+");
                button_m8 = new Button("-");
                button_p9 = new Button("+");
                button_m9 = new Button("-");
               
                list_compLabel.get(5).setText(att.get(0).getName());
                list_compLabel.get(6).setText(att.get(1).getName());
               
                addCaracteristique(list_compLabel.get(5), list_compInput.get(5), button_p8, button_m8, panel_carac1,"spe");
                addCaracteristique(list_compLabel.get(6), list_compInput.get(6), button_p9, button_m9, panel_carac2,"spe");
          }
       
        /*******************************************************************************
         * Calcule le nombre de point distribue pour les attaques normales
         *
         * @return faux si le maximum a été atteind et vrai dans le cas contraire
         ******************************************************************************/
            private boolean max_caract(){
                int int1 = Integer.parseInt(list_compInput.get(0).getValue());
                int int2 = Integer.parseInt(list_compInput.get(1).getValue());
                int int3 = Integer.parseInt(list_compInput.get(2).getValue());
                int int4 = Integer.parseInt(list_compInput.get(3).getValue());
                int int5 = Integer.parseInt(list_compInput.get(4).getValue());
               
                int total = int1+int2+int3+int4+int5;
               
                if (total == 50){
                        return false;
                }
                        return true;    
            }

         /*******************************************************************************
         * Calcule le nombre de point distribue pour les attaques speciales
         *
         * @return faux si le maximum a été atteind et vrai dans le cas contraire
         ******************************************************************************/
            public boolean max_caract_spe(){
                int int1 = Integer.parseInt(list_compInput.get(5).getValue());
                int int2 = Integer.parseInt(list_compInput.get(6).getValue());
                
                int total = int1+int2;
                if (total == 20) return false;
                
                return true;    
            }
           
         /*******************************************************************************
         * Reinitialise la vue
         *
         ******************************************************************************/
            public void clearView(){
                imagePanel.clear();
                        upload_image(uploadSubmitButton);
                       
                vider_champs();

                this.troll = null;
                this.img = img_default;
                
                button_save.setText("Enregistrer");
                button_del.setStyleName("action_btn hidden");
                uploadForm.reset();
            }
           
     /*******************************************************************************
     * Permet de vider tous les champs
     *
     ******************************************************************************/
     public void vider_champs(){
        nom_troll.setEnabled(true);
        getNom_troll().setValue("");
        for (int i = 0 ; i<5; i++){
                list_compInput.get(i).setValue("0");
        }
        if (dropBox.getItemText(dropBox.getSelectedIndex()) != null){
                dropBox.setSelectedIndex(0);
                panel_carac1.clear(); panel_carac2.clear();
        }
     }
           
	 /*******************************************************************************
	 * incrementer champ point attaque spe si les limites ne sont pas atteintes
	 *
	 * @param le champ
	 ******************************************************************************/
	 private void max_point_spe(TextBox champ){
	    int mon_int = Integer.parseInt(champ.getValue());
	   
	    if (mon_int == 20 || max_caract_spe() == false){
	            champ.setText(""+mon_int);
	    }else{
	            mon_int = mon_int + 1;
	            champ.setText(""+mon_int);
	    }
	 }
           
     /*******************************************************************************
     * incrementer champ point attaque normales si les limites ne sont pas atteintes
     *
     * @param le champ
     ******************************************************************************/
	private void max_point(TextBox champ){
	    int mon_int = Integer.parseInt(champ.getValue());
	   
	    if (mon_int == 50 || max_caract() == false){
	        champ.setText(""+mon_int);
	    } else {
            mon_int = mon_int + 1;
            champ.setText(""+mon_int);
	    }
	}
            
	 /*******************************************************************************
	 * decrementer champ point si les limites ne sont pas atteintes
	 *
	 * @param le champ
	 ******************************************************************************/
	private void min_point(TextBox champ){
	   
	    int mon_int = Integer.parseInt(champ.getValue());
	   
	    if (mon_int == 0) {
	        champ.setText(""+mon_int);
		} else {
	        mon_int = mon_int - 1;
	        champ.setText(""+mon_int);
		}
	}
	     
    /*******************************************************************************
     * Afficher les caractéristiques
     *
     * @param label, champ, buttonp, buttonm, panel , spe ~ Le dernier paramétre permet de differencier les attaques spe des attaques normales
     ******************************************************************************/        
    private void addCaracteristique(Label label, final TextBox champ, Button buttonp, Button buttonm, HorizontalPanel panel,final String spe){

        panel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_LEFT);
        panel.setSpacing(10);
       
        champ.setStyleName("textPoint");
        if(champ.getValue()=="") champ.setText("0");
        champ.setEnabled(false);
        champ.setPixelSize(20, 20);
       
        buttonp.setStyleName("buttonPlus");
        buttonp.setEnabled(true);
        buttonp.addClickHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent event) {
                if (spe == "normal"){
                        max_point(champ);}
                else if (spe == "spe") {
                        max_point_spe(champ);}
            }
        });
        buttonm.setStyleName("buttonMoins");
        buttonm.getElement().setId("m5");
        buttonm.setEnabled(true);
        buttonm.addClickHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent event) {
                min_point(champ);
            }
        });

        panel.add(label);
        panel.add(buttonm);
        panel.add(champ);
        panel.add(buttonp);
    }
           
    public static ViewTroll get() {
        return SINGLETON;
    }
            
    /*******************************************************************************
     * setter du troll @troll
     * met à jour les données affichées avec celles du troll
     *
     * @param troll ~ non null, non vide
     ******************************************************************************/
    public void setTroll(Troll troll) {
    	clearView();
        this.troll = troll;
        this.img = troll.getImg();
        
        /* le nom */
        getNom_troll().setText(troll.getName());

        /* les competences */
        HashMap<Attribut, Integer> comp = troll.getCompetences();
        if(comp.isEmpty() || comp==null) return;
        
        Integer i = 0;
        for (Attribut item : comp.keySet()) {
			 list_compLabel.get(i).setText(item.getName());
			 list_compInput.get(i).setText("" + comp.get(item));
			 i++;
        }
        
        /* la race + les caracteres */
	    updateRace();
	        
	   /* l'image */
	   showImage(troll.getImg());
	   
	   /* les button */
	   button_save.setText("Modifier");
	   button_del.removeStyleName("hidden");
    }
    
    /*******************************************************************************
     * setter du hashmap @races
     *
     * @param races ~ hashmap de races
     ******************************************************************************/
    public void setRaces(HashMap<String, Race> races) {
        if(races!=null && !races.isEmpty())
                this.races = races;
       
        updateRace();
    }
   
    /*******************************************************************************
     * met à jour la liste de races en fonction de @races
     ******************************************************************************/
    private void updateRace() {
        dropBox.clear();
       
        if(races.isEmpty() || races==null) {
            dropBox.addItem("AUCUNE RACE ?"); //ça n'est pas censé arriver
            return;
        }

        dropBox.addItem("");
        for (String item : races.keySet()) {
                if((troll!=null && troll.getRace().getName().contentEquals(item))
                        || !races.get(item).getCaracteristiques().isEmpty()) {
                        //on n'affiche pas les races qui n'ont pas été initialisées
                        //(arrive si cette race à été supprimée mais qu'il existe encore des trolls de cette race par ex)
                        dropBox.addItem(item);
                }
        }
       
        //on selectionne la race du troll
        if(troll!=null) {
                for(int i=0; i<dropBox.getItemCount(); i++) {
                        if(dropBox.getItemText(i).contentEquals(troll.getRace().getName())) {
                                dropBox.setSelectedIndex(i);
                        }
                }
                showRace(troll.getRace().getName());
        }
    }
	/*******************************************************************************
     * getteur sur nom_troll
     ******************************************************************************/
    public TextBox getNom_troll() {
            return nom_troll;
    }
    /*******************************************************************************
     * Obtenir la valeur du textBox nom_troll
     ******************************************************************************/
    public String getValeur_nom_troll() {
            return nom_troll.getValue();
    }
    /*******************************************************************************
     * Setteur sur nom_troll
     ******************************************************************************/
    public void setNom_troll(TextBox nom_troll) {
            this.nom_troll = nom_troll;
    }
       
	/*******************************************************************************
	 * Affiche le form de l'upload de l'image avec en parametre le boutton envoyer
	 * @param button_envoyer ~ Le bouton qui permet d'effectuer le submit
	 ******************************************************************************/
	public void upload_image(Button boutton_envoyer){                      
        // Associé un service au formulaire
        uploadForm.setAction(GWT.getModuleBaseURL() + "UploadFileServlet");
       
        // Pour ajouter un FileUpload widget, nous devons ajouter au formulaire
        // une méthode d'envoie POST, et un encodage multipart MIME.
        uploadForm.setEncoding(FormPanel.ENCODING_MULTIPART);
        uploadForm.setMethod(FormPanel.METHOD_POST);
       
        // Ajout du panel au formulaire
        uploadForm.setWidget(panel);
       
        // Propriétés du FileUpload widget
        upload.setName("TMP");
        
        panel.add(upload);
       
        // Ajout du label message serveur
        panel.add(messageServeur);
   
        //bouton submit
        panel.add(boutton_envoyer);
        uploadSubmitButton.addClickHandler(new ClickHandler() {
               
            public void onClick(ClickEvent event) {
                upload.setName(directory + "/" + "TMP-" + this.hashCode());
                uploadForm.submit();
            }
        });
        uploadForm.addSubmitCompleteHandler(new SubmitCompleteHandler() {
            public void onSubmitComplete(SubmitCompleteEvent event) {
                    showImage(event.getResults());
            }
        });
        imagePanel.add(uploadForm);
	}
       
	/*******************************************************************************
	 * Permet d'afficher l'image selectionné
	 * @param panel, chemin ~ Le panel dans lequel l'image est affiché et le nom de celle ci
	 ******************************************************************************/
	public void showImage(String chemin){
        imagePanel.clear();
       
        //on garde l'image
        chemin = chemin.replace("<pre>",""); chemin = chemin.replace("</pre>",""); //supprime les balises avant et aprés le nom de l'image
        this.img = chemin;
       
        //ajoute l'image
        Image monImage = new Image(chemin);
        monImage.setSize("300px", "300px");
        imagePanel.add(monImage);
       
        //ajoute le form d'upload
        upload_image(uploadSubmitButton);
	}
}